#include "../include/search_engine.h"
#include <sstream>
#include <algorithm>
#include <iomanip>

SearchEngine::SearchEngine() {
}

SearchEngine::~SearchEngine() {
}

std::vector<SearchResult> SearchEngine::search(const std::string& query, int user_id) {
    std::vector<SearchResult> results;
    
    // Get user keyword weights
    std::map<std::string, double> keyword_weights;
    if (user_id > 0) {
        // This should get user keyword weights from database
        // Temporarily use example weights
        keyword_weights["cpp"] = 2.0;
        keyword_weights["search"] = 1.5;
    }
    
    // Call Baidu search API
    results = baiduSearch(query);
    
    // Recalculate relevance scores based on weights
    for (auto& result : results) {
        result.relevance_score = calculateRelevanceScore(result, query, keyword_weights);
    }
    
    // Sort by relevance score
    std::sort(results.begin(), results.end(), 
              [](const SearchResult& a, const SearchResult& b) {
                  return a.relevance_score > b.relevance_score;
              });
    
    return results;
}

bool SearchEngine::setKeywordWeight(int user_id, const std::string& keyword, double weight) {
    // This should call the database manager to set keyword weight
    return true;
}

double SearchEngine::getKeywordWeight(int user_id, const std::string& keyword) {
    // This should call the database manager to get keyword weight
    return 1.0;
}

std::vector<SearchResult> SearchEngine::baiduSearch(const std::string& query) {
    std::vector<SearchResult> results;
    
    // Since we don't have CURL, return sample results
    SearchResult result;
    result.title = "C++ Search Engine - Sample Result for: " + query;
    result.url = "https://example.com/search?q=" + urlEncode(query);
    result.description = "This is a sample search result for the query: " + query + 
                        ". In a real implementation, this would connect to Baidu's search API.";
    result.relevance_score = 1.0;
    results.push_back(result);
    
    // Add another sample result
    SearchResult result2;
    result2.title = "C++ Programming Resources";
    result2.url = "https://example.com/cpp-resources";
    result2.description = "Learn C++ programming with comprehensive tutorials and examples.";
    result2.relevance_score = 0.8;
    results.push_back(result2);
    
    return results;
}

double SearchEngine::calculateRelevanceScore(const SearchResult& result, const std::string& query, 
                                           const std::map<std::string, double>& keyword_weights) {
    double score = result.relevance_score;
    
    // Extract query keywords
    std::vector<std::string> keywords = extractKeywords(query);
    
    // Adjust score based on keyword weights
    for (const auto& keyword : keywords) {
        auto it = keyword_weights.find(keyword);
        if (it != keyword_weights.end()) {
            score *= it->second;
        }
    }
    
    return score;
}

std::string SearchEngine::makeHttpRequest(const std::string& url, const std::map<std::string, std::string>& headers) {
    // Simplified implementation without CURL
    return "<html><body><h1>Sample Response</h1><p>This is a sample HTTP response.</p></body></html>";
}

std::vector<SearchResult> SearchEngine::parseBaiduResults(const std::string& response) {
    std::vector<SearchResult> results;
    
    // Simple parsing without HTML library
    if (response.find("Sample Response") != std::string::npos) {
        SearchResult result;
        result.title = "Sample Search Result";
        result.url = "https://example.com";
        result.description = "This is a sample search result from simplified parsing.";
        result.relevance_score = 1.0;
        results.push_back(result);
    }
    
    return results;
}

std::string SearchEngine::urlEncode(const std::string& str) {
    std::ostringstream escaped;
    escaped.fill('0');
    escaped << std::hex;
    
    for (char c : str) {
        if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
            escaped << c;
        } else {
            escaped << std::uppercase;
            escaped << '%' << std::setw(2) << int((unsigned char) c);
            escaped << std::nouppercase;
        }
    }
    
    return escaped.str();
}

std::vector<std::string> SearchEngine::extractKeywords(const std::string& query) {
    std::vector<std::string> keywords;
    std::istringstream iss(query);
    std::string word;
    
    while (iss >> word) {
        // Remove punctuation
        word.erase(std::remove_if(word.begin(), word.end(), ispunct), word.end());
        if (!word.empty()) {
            keywords.push_back(word);
        }
    }
    
    return keywords;
}